package com.edu.app.controller.ai;

import com.edu.app.bean.core.SysUser;
import com.edu.app.bean.virtualbean.KeyValueItems;
import com.edu.app.bean.virtualbean.NameValueItems;
import com.edu.app.bean.virtualbean.UserActByDate;
import com.edu.app.bean.virtualbean.customize.SalesCommon;
import com.edu.app.bean.virtualbean.customize.SalesPerf;
import com.edu.app.bean.virtualbean.customize.SalesRank;
import com.edu.app.constant.SysMessage;
import com.edu.app.model.customer.CustomerNotActiveModel;
import com.edu.app.service.sys.ai.SysAISalesService;
import com.edu.app.service.sys.ai.SysAIService;
import com.edu.app.service.sys.core.SysListOfValueService;
import com.edu.app.service.sys.core.SysUserService;
import com.edu.app.threadlocal.TenantContext;
import com.edu.app.util.ErrorUtil;
import com.edu.app.util.JWTUtil;
import com.edu.app.util.MsgUtil;

import com.github.pagehelper.PageInfo;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

@RequestMapping(value = "/api/ai/sales")
@RestController
public class SysAISalesController {
    @Autowired
    SysAIService sysAIService;

    @Autowired
    SysAISalesService sysAISalesService;

    @Autowired
    SysListOfValueService sysListOfValueService;

    @Autowired
    SysUserService sysUserService;

    @GetMapping("/getNotActiveCustomersMine")
    @RequiresAuthentication
    public ModelMap getNotActiveCustomersMine(@RequestHeader("Authorization") String token, @RequestParam Integer range){
        try{
            String username = JWTUtil.getUsername(token);
            List<CustomerNotActiveModel> sysCustomerList = sysAISalesService.getNotActiveCustomerByUser(username, range);
            return MsgUtil.retMsg(SysMessage.GET_NOT_ACTIVE_CUSTOMER_SUCCEED, "customers", sysCustomerList);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getNotActiveCustomers")
    @RequiresAuthentication
    public ModelMap getNotActiveCustomersMine(@RequestParam Integer range){
        try{
            List<CustomerNotActiveModel> sysCustomerList = sysAISalesService.getNotActiveCustomer(range);
            return MsgUtil.retMsg(SysMessage.GET_NOT_ACTIVE_CUSTOMER_SUCCEED, "customers", sysCustomerList);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getMyCustomerWithDemoClassToday")
    @RequiresAuthentication
    public ModelMap getMyCustomerWithDemoClassToday(@RequestHeader("Authorization") String token){
        try{
            String username = JWTUtil.getUsername(token);
            List<KeyValueItems> sysCustomerList = sysAISalesService.getCustomerWithDemoClassToday(username);
            return MsgUtil.retMsg(SysMessage.GET_NOT_ACTIVE_CUSTOMER_SUCCEED, "customers", sysCustomerList);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getMyCustomerWithDemoClassFuture")
    @RequiresAuthentication
    public ModelMap getMyCustomerWithDemoClassFuture(@RequestHeader("Authorization") String token){
        try{
            String username = JWTUtil.getUsername(token);
            List<NameValueItems> sysCustomerList = sysAISalesService.getCustomerWithDemoClassFuture(username);
            return MsgUtil.retMsg(SysMessage.GET_NOT_ACTIVE_CUSTOMER_SUCCEED, "customers", sysCustomerList);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getSalesAIModel")
    @RequiresAuthentication
    public ModelMap getSalesAIModel(@RequestParam String username, @RequestParam String date, @RequestParam String actType, @RequestParam String role){
        try{
            /*String username = JWTUtil.getUsername(token);
            List<KeyValueItems> sysCustomerListWithDemoToday = sysAISalesService.getCustomerWithDemoClassToday(username);
            List<NameValueItems> sysCustomerListWithDemoFuture = sysAISalesService.getCustomerWithDemoClassFuture(username);
            List<CustomerNotActiveModel> sysCustomerListNotActive = sysAISalesService.getNotActiveCustomerByUser(username, 3);
            NameValueItems demoClassRank = sysAISalesService.getSalesDemoClassRank(username);
            NameValueItems salesContractNumber = sysAISalesService.getSalesContractNumber(username);
            NameValueItems salesContractTotalAmount = sysAISalesService.getSalesContractTotalAmount(username);*/
            List<UserActByDate> userActByDateList = sysAIService.getUserActListByDateWithRoleAndUser(date,"consultant", username, actType);
            List<CustomerNotActiveModel> sysCustomerListNotActive = sysAISalesService.getNotActiveCustomerByUser(username, 3);
            ModelMap map = MsgUtil.retMsg(SysMessage.GET_SALES_AI_MODEL_SUCCEED, "tomorrowAct", userActByDateList);
            map.put("customerNotActive",sysCustomerListNotActive);
            return map;
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getSalesRankByDay")
    @RequiresAuthentication
    public ModelMap getSalesRankByDay(){
        try{
            List<NameValueItems> salesDemoClassRankAllByDay = sysAISalesService.getSalesDemoClassRankAllByDay();
            List<NameValueItems> salesContractNumberAllByDay = sysAISalesService.getSalesContractNumberAllByDay();
            List<NameValueItems> salesContractTotalAmountAllByDay = sysAISalesService.getSalesContractTotalAmountAllByDay();
            ModelMap map = MsgUtil.retMsg(SysMessage.GET_SALES_RANK_SUCCEED, "salesDemoClassRank", salesDemoClassRankAllByDay);
            map.put("salesContractNumberRank",salesContractNumberAllByDay);
            map.put("salesContractTotalAmountRank", salesContractTotalAmountAllByDay);
            return map;
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getSalesRankByWeek")
    @RequiresAuthentication
    public ModelMap getSalesRankByWeek(){
        try{
            List<NameValueItems> salesDemoClassRankAllByWeek = sysAISalesService.getSalesDemoClassRankAllByWeek();
            List<NameValueItems> salesContractNumberAllByWeek = sysAISalesService.getSalesContractNumberAllByWeek();
            List<NameValueItems> salesContractTotalAmountAllByWeek = sysAISalesService.getSalesContractTotalAmountAllByWeek();
            ModelMap map = MsgUtil.retMsg(SysMessage.GET_SALES_RANK_SUCCEED, "salesDemoClassRank", salesDemoClassRankAllByWeek);
            map.put("salesContractNumberRank",salesContractNumberAllByWeek);
            map.put("salesContractTotalAmountRank", salesContractTotalAmountAllByWeek);
            return map;
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping("/getSalesRankByMonth")
    @RequiresAuthentication
    public ModelMap getSalesRankByMonth(@RequestParam String date){
        try{
            List<NameValueItems> salesDemoClassRankAllByMonth = sysAISalesService.getSalesDemoClassRankAllByMonth();
            List<NameValueItems> salesContractNumberAllByMonth = sysAISalesService.getSalesContractNumberAllByMonth();
            List<NameValueItems> salesContractTotalAmountAllByMonth = sysAISalesService.getSalesContractTotalAmountAllByMonth(date);
            ModelMap map = MsgUtil.retMsg(SysMessage.GET_SALES_RANK_SUCCEED, "salesDemoClassRank", salesDemoClassRankAllByMonth);
            map.put("salesContractNumberRank",salesContractNumberAllByMonth);
            map.put("salesContractTotalAmountRank", salesContractTotalAmountAllByMonth);
            return map;
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping(value = "/pages/getPoCustomerModel")
    @RequiresAuthentication
    public ModelMap getPoCustomerModel(@RequestParam Integer offset,
                                       @RequestParam Integer limit,
                                       @RequestParam String orderBy,
                                       @RequestParam String sequence){
        try{
            //avoid SQL injection
            String order = getOrderForPoCusList(orderBy);
            String seq = getSeq(sequence);

            PageInfo pageInfo = sysAISalesService.getPoCustomerModel(offset, limit, order, seq);
            return MsgUtil.retMsg(SysMessage.GET_PO_CUSTOMER_LIST_SUCCEED, "page_info", pageInfo);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping(value = "/pages/getAllPoCustomerModel")
    @RequiresAuthentication
    public ModelMap getAllPoCustomerModel(@RequestParam Integer offset,
                                       @RequestParam Integer limit,
                                       @RequestParam String orderBy,
                                       @RequestParam String sequence,
                                       @RequestParam Integer status){
        try{
            String order = getOrder(orderBy);
            String seq = getSeq(sequence);

            PageInfo pageInfo = sysAISalesService.getAllPoCustomerModel(offset, limit, order, seq, status);
            return MsgUtil.retMsg(SysMessage.GET_PO_CUSTOMER_LIST_SUCCEED, "page_info", pageInfo);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping(value = "/pages/getAllDemoClassPoCustomerModel")
    @RequiresAuthentication
    public ModelMap getAllDemoClassPoCustomerModel(@RequestParam Integer offset,
                                          @RequestParam Integer limit,
                                          @RequestParam String orderBy,
                                          @RequestParam String sequence,
                                          @RequestParam Integer status){
        try{
            String order = getOrder(orderBy);
            String seq = getSeq(sequence);

            PageInfo pageInfo = sysAISalesService.getAllDemoClassPoCustomerModel(offset, limit, order, seq, status);
            return MsgUtil.retMsg(SysMessage.GET_PO_CUSTOMER_LIST_SUCCEED, "page_info", pageInfo);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping(value = "/pages/getMyCustomerModel")
    @RequiresAuthentication
    public ModelMap getMyCustomerModel(@RequestParam Integer offset,
                                         @RequestParam Integer limit,
                                         @RequestParam String orderBy,
                                         @RequestParam String sequence,
                                         @RequestParam String username,
                                         @RequestParam Integer status){
        try{
            String order = getOrder(orderBy);
            String seq = getSeq(sequence);

            PageInfo pageInfo = sysAISalesService.getMyCustomerModel(offset, limit, order, seq, username, status);
            return MsgUtil.retMsg(SysMessage.GET_PO_CUSTOMER_LIST_SUCCEED, "page_info", pageInfo);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    private String getOrder(String str){

        if(str.equalsIgnoreCase("days")){
            return "days";
        }else if(str.equalsIgnoreCase("consultant")){
            return "consultant";
        }else if(str.equalsIgnoreCase("tag")){
            return "tag";
        }else if(str.equalsIgnoreCase("name")){
            //return "convert(name using gbk)";
            return "CAST(name AS CHAR CHARACTER SET gbk)"; //to support sql92 for jsqlparser
        }else if(str.equalsIgnoreCase("employee")){
            //return "convert(name using gbk)";
            return "CAST(employee AS CHAR CHARACTER SET gbk)"; //to support sql92 for jsqlparser
        }else if(str.equalsIgnoreCase("age")){
            return "age";
        }else if(str.equalsIgnoreCase("stage")){
            return "stage";
        }else if(str.equalsIgnoreCase("quality_tag")){
            return "quality_tag";
        }else if(str.equalsIgnoreCase("channel_tag")){
            return "channel_tag";
        }else if(str.equalsIgnoreCase("contract_time")){
            return "contract_time";
        }else if(str.equalsIgnoreCase("amount")){
            return "amount";
        }else if(str.equalsIgnoreCase("time")){
            return "time";
        }else{
            return "days";
        }
    }

    private String getOrderForPoCusList(String str){

        if(str.equalsIgnoreCase("days")){
            return "days";
        }else if(str.equalsIgnoreCase("consultant")){
            return "consultant";
        }else if(str.equalsIgnoreCase("tag")){
            return "tag";
        }else if(str.equalsIgnoreCase("name")){
            //return "convert(name using gbk)";
            return "CAST(name AS CHAR CHARACTER SET gbk)"; //to support sql92 for jsqlparser
        }else if(str.equalsIgnoreCase("age")){
            return "age";
        }else if(str.equalsIgnoreCase("stage")){
            return "stage";
        }else if(str.equalsIgnoreCase("quality_tag")){
            return "quality_tag";
        }else if(str.equalsIgnoreCase("channel_tag")){
            return "channel_tag";
        }else{
            return "days";
        }
    }

    private String getOrderForMarketing(String str){

        if(str.equalsIgnoreCase("days")){
            return "days";
        }else if(str.equalsIgnoreCase("tag")){
            return "tag";
        }else if(str.equalsIgnoreCase("name")){
            //return "convert(name using gbk)";
            return "CAST(name AS CHAR CHARACTER SET gbk)"; //to support sql92 for jsqlparser
        }else if(str.equalsIgnoreCase("age")){
            return "age";
        }else if(str.equalsIgnoreCase("quality_tag")){
            return "quality_tag";
        }else if(str.equalsIgnoreCase("channel_tag")){
            return "channel_tag";
        }else{
            return "days";
        }
    }

    private String getSeq(String str){
        if(str.equalsIgnoreCase("asc")){
            return "asc";
        }else if(str.equalsIgnoreCase("desc")){
            return "desc";
        }else{
            return "asc";
        }
    }

    @GetMapping(value = "/getPerformanceByUser")
    @RequiresAuthentication
    public ModelMap getPerformanceByUser(@RequestParam String username,
                                         @RequestParam String date,
                                         @RequestParam Integer type){
        try{
            NameValueItems telNumber;
            NameValueItems visitNumber;
            NameValueItems demoNumber;
            NameValueItems contractNumber;
            NameValueItems poCusNumber;
            NameValueItems cusNumber;
            NameValueItems rawCusNumber;
            switch (type) {
                case 0:
                    telNumber = sysAISalesService.getActNumberByTypeAndDay(username, "S_LOV_SALES_PHONE", date);
                    visitNumber = sysAISalesService.getActNumberByTypeAndDay(username, "S_LOV_SALES_VISIT", date);
                    demoNumber = sysAISalesService.getActNumberByTypeAndDay(username, "S_LOV_SALES_DEMO", date);
                    contractNumber = sysAISalesService.getContractNumberByDay(username, date);
                    break;
                case 1:
                    telNumber = sysAISalesService.getActNumberByTypeAndWeek(username, "S_LOV_SALES_PHONE", date);
                    visitNumber = sysAISalesService.getActNumberByTypeAndWeek(username, "S_LOV_SALES_VISIT", date);
                    demoNumber = sysAISalesService.getActNumberByTypeAndWeek(username, "S_LOV_SALES_DEMO", date);
                    contractNumber = sysAISalesService.getContractNumberByWeek(username, date);
                    break;
                case 2:
                    telNumber = sysAISalesService.getActNumberByTypeAndMonth(username, "S_LOV_SALES_PHONE", date);
                    visitNumber = sysAISalesService.getActNumberByTypeAndMonth(username, "S_LOV_SALES_VISIT", date);
                    demoNumber = sysAISalesService.getActNumberByTypeAndMonth(username, "S_LOV_SALES_DEMO", date);
                    contractNumber = sysAISalesService.getContractNumberByMonth(username, date);
                    break;
                default:
                    telNumber = sysAISalesService.getActNumberByTypeAndDay(username, "S_LOV_SALES_PHONE", date);
                    visitNumber = sysAISalesService.getActNumberByTypeAndDay(username, "S_LOV_SALES_VISIT", date);
                    demoNumber = sysAISalesService.getActNumberByTypeAndDay(username, "S_LOV_SALES_DEMO", date);
                    contractNumber = sysAISalesService.getContractNumberByDay(username, date);
                    break;
            }

            poCusNumber = sysAISalesService.getCusNumberByType(username, 0);
            cusNumber = sysAISalesService.getCusNumberByType(username, 1);
            rawCusNumber = sysAISalesService.getCusNumberByType(username, 8);

            ModelMap map = MsgUtil.retMsg(SysMessage.GET_SALES_PERF_SUCCEED, "telNumber", telNumber);
            map.put("visitNumber", visitNumber);
            map.put("demoNumber", demoNumber);
            map.put("contractNumber", contractNumber);
            map.put("poCusNumber", poCusNumber);
            map.put("cusNumber", cusNumber);
            map.put("rawCusNumber", rawCusNumber);

            return map;
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping(value = "/getSalesPerf")
    @RequiresAuthentication
    public ModelMap getSalesPerf(@RequestParam String date,
                                 @RequestParam Integer type){
        try{
            List<SysUser> sysSalesList = sysAISalesService.getSalesList();
            List<SalesRank> salesRankList = new ArrayList<>();
            List<SalesCommon> salesCommonList = null;
            List<SalesPerf> salesPerfList = null;
            switch (type){
                case 0:
                    salesCommonList = sysAISalesService.getActNumberByTypeAndDayAll(date);
                    salesPerfList = sysAISalesService.getContractNumberAndAmountByDayAll(date);
                    break;
                case 1:
                    salesCommonList = sysAISalesService.getActNumberByTypeAndWeekAll(date);
                    salesPerfList = sysAISalesService.getContractNumberAndAmountByWeekAll(date);
                    break;
                case 2:
                    salesCommonList = sysAISalesService.getActNumberByTypeAndMonthAll(date);
                    salesPerfList = sysAISalesService.getContractNumberAndAmountByMonthAll(date);
                    break;
                default:
                    salesCommonList = sysAISalesService.getActNumberByTypeAndDayAll(date);
                    salesPerfList = sysAISalesService.getContractNumberAndAmountByDayAll(date);
                    break;
            }

            for(SysUser item: sysSalesList){
                SalesRank salesRank = new SalesRank();
                salesRank.setId(item.getId());
                salesRank.setNickname(item.getNickname());

                for(SalesCommon salesCommon: salesCommonList){
                    if(salesCommon.getId() == salesRank.getId()){
                        if (salesCommon.getType().equalsIgnoreCase("电话")){
                            salesRank.setTelNumber(salesCommon.getValue());
                        }else if(salesCommon.getType().equalsIgnoreCase("到访")){
                            salesRank.setVisitNumber(salesCommon.getValue());
                        }else if(salesCommon.getType().equalsIgnoreCase("试听")){
                            salesRank.setDemoNumber(salesCommon.getValue());
                        }
                    }
                }

                for(SalesPerf salesPerf: salesPerfList){
                    if(salesPerf.getId() == salesRank.getId()){
                        salesRank.setContractNumber(salesPerf.getValue1());
                        salesRank.setCusTotalAmount(salesPerf.getValue2());
                    }
                }

                NameValueItems poCusNumber = sysAISalesService.getCusNumberByType(item.getUsername(), 0);
                NameValueItems cusNumber = sysAISalesService.getCusNumberByType(item.getUsername(), 1);
                NameValueItems rawCusNumber = sysAISalesService.getCusNumberByType(item.getUsername(), 8);

                if(poCusNumber != null){
                    salesRank.setPoCusNumber(poCusNumber.getValue());
                }

                if(cusNumber != null){
                    salesRank.setCusNumber(cusNumber.getValue());
                }

                if(rawCusNumber != null){
                    salesRank.setRawCusNumber(rawCusNumber.getValue());
                }

                salesRankList.add(salesRank);
            }

            {
                Comparator<SalesRank> comparator = new Comparator<SalesRank>(){
                    public int compare(SalesRank s1, SalesRank s2) {
                        //先排销售额
                        if(s1.getCusTotalAmount() != s2.getCusTotalAmount()){
                            return s2.getCusTotalAmount() - s1.getCusTotalAmount();
                        }

                        //再排加权
                        Integer sub = (s2.getTelNumber() + 10*s2.getVisitNumber() + 10*s2.getDemoNumber() + 100*s2.getContractNumber()) - (s1.getTelNumber() + 10*s1.getVisitNumber() + 10*s1.getDemoNumber() + 100*s1.getContractNumber());
                        if(sub != 0){
                            return sub;
                        }
                        else{
                            //加权相同，再看总准客户数
                            if(s1.getPoCusNumber()!=s2.getPoCusNumber()){
                                return s2.getPoCusNumber()-s1.getPoCusNumber();
                            }
                            else{
                                //最后以id来排序
                                return s2.getCusNumber()-s1.getCusNumber();
                            }
                        }
                    }
                };

                Collections.sort(salesRankList,comparator);
            }

            ModelMap map = MsgUtil.retMsg(SysMessage.GET_SALES_PERF_SUCCEED, "salesRankList", salesRankList);
            return map;
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    //TODO
    @GetMapping(value = "/getSalesPerfByDay")
    @RequiresAuthentication
    public ModelMap getSalesPerfByDay(@RequestParam String date){
        List<SalesPerf> salesPerfList = sysAISalesService.getSalesPerfByDay(date);
        return MsgUtil.retMsg(SysMessage.GET_SALES_PERF_SUCCEED, "salesRankByDay", salesPerfList);
    }

    @GetMapping(value = "/getSalesPerfByDayWithName")
    @RequiresAuthentication
    public ModelMap getSalesPerfByDayWithName(@RequestParam String date, @RequestParam String username){
        List<SalesPerf> salesPerfList = sysAISalesService.getSalesPerfByDayWithName(date,username);
        return MsgUtil.retMsg(SysMessage.GET_SALES_PERF_SUCCEED, "salesRankByDay", salesPerfList);
    }

    @GetMapping(value = "/pages/getCustomerNotAssignedModel")
    @RequiresAuthentication
    public ModelMap getCustomerNotAssignedModel(@RequestParam Integer offset,
                                       @RequestParam Integer limit,
                                       @RequestParam String orderBy,
                                       @RequestParam String sequence){
        try{
            //avoid SQL injection
            String order = getOrderForMarketing(orderBy);
            String seq = getSeq(sequence);

            PageInfo pageInfo = sysAISalesService.getCustomerNotAssignedModel(offset, limit, order, seq);
            return MsgUtil.retMsg(SysMessage.GET_PO_CUSTOMER_LIST_SUCCEED, "page_info", pageInfo);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

}
